var MODELO = {

	Tienda : function(nombreTienda) {
		this.nombreTienda = nombreTienda;
		this.clientes = new MODELO.Clientes();
		this.categoriasArticulos = new MODELO.Categorias();
		this.pedidos = new MODELO.Pedidos();
		
		//Observe que también podemos poner la adición de elementos en la propia tienda en vez de en las clases
		//Importante: No estoy retornando el objeto al que se añaden las categorías, sino el objeto que estoy añadiendo
		//ya que el que llama al método no tiene una referencia a él.
		this.addCategoria = function (id, nombre) {
			var categoria = new MODELO.Categoria(id, nombre);
			this.categoriasArticulos.addElemento(categoria);
			return categoria;
		}
	},

	Cliente : function(id, nombre) {
		this.elemento = MODELO.Elemento;
		this.elemento(id, nombre, MODELO.CLASES.Cliente, LITERALES.Cliente);
		delete this.elemento;
		
		
	},

	Clientes : function() {
		this.lista = MODELO.Lista;
		this.lista(0, null, MODELO.CLASES.Clientes, LITERALES.Clientes);
		delete this.lista;
		
		this.addCliente = function (cliente) {
			return this.addElemento(cliente);
		}

	},

	Categoria : function(id, nombre) {
		this.lista = MODELO.Lista;
		this.lista(id, nombre, MODELO.CLASES.Categoria, LITERALES.Categoria);
		delete this.lista;
		
		this.addArticulo = function (id, nombre, precioArticulo) {
			return this.addElemento(new MODELO.Articulo(id, nombre, precioArticulo,this));
		}
	},

	Articulo : function(id, nombre, precioArticulo, categoria) {
		this.elemento = MODELO.Elemento;
		this.elemento(id, nombre, MODELO.CLASES.Articulo, LITERALES.Articulo, categoria);
		delete this.elemento;
		this.precioArticulo = precioArticulo;

	},

	Categorias : function() {
		this.lista = MODELO.Lista;
		this.lista(0, null, MODELO.CLASES.Categorias, LITERALES.Categorias);
		delete this.lista;
		
		this.addCategoria = function (categoria) {
			return this.addElemento(categoria);
		}
	},

	Pedido : function(idPedido, cliente, fechaPedido) {
		this.elemento = MODELO.Elemento;
		this.elemento(idPedido, idPedido, MODELO.CLASES.Pedido, LITERALES.Pedido);
		delete this.elemento;

		this.cliente = cliente;
		this.fechaPedido = fechaPedido;
		var lineas = new MODELO.Lista(0, null, MODELO.CLASES.LineasPedido, LITERALES.LineasPedido);

		this.importePedido = function() {
			return lineas.elementos.reduce(function(suma, linea) {
				return suma + linea.importeLinea();
			}, 0);
		};

		this.masDatos = function() {
			var s = LITERALES.Total + " " + this.importePedido().toFixed(2);
			s += "\n"+lineas.toString(); 
			return s;
		}

		this.getLineas = function() {
			return lineas;
		}

		this.addLinea = function(articulo, cantidadArticulo, precioVenta, orden) {
			lineas.addElemento(new MODELO.LineaPedido(this,articulo, cantidadArticulo, precioVenta, orden));
		}

	},

	LineaPedido : function(pedido, articulo, cantidadArticulo, precioVenta, orden) {
		if (orden) {
			this.orden = orden;
		} else {
			this.orden = pedido.getLineas().tam() + 1;
		}

		this.elemento = MODELO.Elemento;
		this.elemento(this.orden, this.orden, MODELO.CLASES.LineaPedido, LITERALES.LineaPedido, pedido);
		delete this.elemento;

		this.articulo = articulo;
		this.cantidadArticulo = cantidadArticulo;
		if (precioVenta !== 0 && precioVenta) {
			this.precioVenta = precioVenta.toFixed(2);
		} else {
			this.precioVenta = this.articulo.precioArticulo;
		}
		this.importeLinea = function() {
			return this.cantidadArticulo * this.precioVenta;
		};
		
		this.masDatos = function() {
			var s = LITERALES.Total + " " + this.importeLinea().toFixed(2);			 
			return s;
		}

	},

	Pedidos : function() {
		this.lista = MODELO.Lista;
		this.lista(0, 0, MODELO.CLASES.Pedidos, LITERALES.Pedidos);
		delete this.lista;
	},

	CLASES : {
		Elemento : 'Elemento',
		Lista : 'Lista',
		Cliente : 'Cliente',
		Clientes : 'Clientes',
		Categoria : 'Categoria',
		Categorias : 'Categorias',
		Articulo : 'Articulo',
		Pedido : 'Pedido',
		Pedidos : 'Pedidos',
		LineaPedido : 'LineaPedido',
	},

	Elemento : function(id, valor, tipo, etiqueta, padre) {
		this.id = id;
		this.valor = valor;
		if (tipo) {
			this.tipo = tipo;
		} else {
			this.tipo = MODELO.CLASES.Elemento;
		}
		this.padre = padre;

		if (etiqueta) {
			this.etiqueta = etiqueta;
		} else {
			this.etiqueta = tipo;
		}

		this.masDatos; // Datos adicionales del mátodo toString ya que no puedo
						// llamar al método con super

		this.toString = function() {
			var s = "";
			if (this.valor) {
				s += this.valor;
			} else {
				s += this.etiqueta;
			}
			for ( var atr in this) {
				if (this[atr] && this[atr].esLista && atr != "padre" ) {
					s += "\n" + this[atr].toString();//PELIGRO DE RECURSIÓN INFINITA. COMENTAR SI DA PROBLEMAS
				} else if (atr != "id" && atr != "tipo" && atr != "valor" && atr != "etiqueta" && atr != "padre"  && typeof this[atr] != "function") {
					s += "\t" + atr + " " + this[atr];
					
				}
			}
			if (this.masDatos) {
				s += "\t" + this.masDatos();
			}
			return s;
		}

		this.equals = function(elemento) {
			return (this.tipo == elemento.tipo && this.id == elemento.id);
		}
	},

	Lista : function(id, valor, tipo, etiqueta, padre) {
		if (tipo) {
			this.tipo = tipo;
		} else {
			this.tipo = MODELO.CLASES.Lista;
		}
		
		this.elemento = MODELO.Elemento;
		this.elemento(id, valor, tipo, etiqueta, padre);
		this.esLista = true;
		delete this.elemento;

		this.elementos = [];

		this.tam = function() {
			return this.elementos.length;
		}
		
		this.addElemento = function(elemento) {
			this.elementos.push(elemento);
			return this;
		}

		this.getElemento = function(idElemento, tipo, busquedaIntrospectiva) {
			var i = 0;
			var elemento = null;

			while (i < this.elementos.length && !elemento) {

				// alert("this.elementos[i]="+this.elementos[i].tipo +" "+
				// tipo);
				if (this.elementos[i].id == idElemento) {
					// alert("aqui");
					if (!tipo | (tipo && this.elementos[i].tipo == tipo)) {
						// alert("aqui2 "+this.elementos[i]);
						elemento = this.elementos[i];
					}
				}

				if (!elemento) {
					if (busquedaIntrospectiva && this.elementos[i].esLista) {
						elemento = this.elementos[i].getElemento(idElemento, tipo, false);
					}
				}

				if (!elemento) {
					i++;
				}

			}

			return elemento;
		}

		this.toString = function() {

			var s = "";
			if (this.valor) {
				s += this.valor;
			} else {
				s += this.etiqueta;
			}

			// s+= ":";

			this.elementos.forEach(function(elemento) {
				s += "\n\t" + elemento.toString();
			});
			return s;
		}
	},

// SIN_CATEGORIA: new Categoria(0,"Sin Clasificar"), -> No funciona. No sé la
// razón. Lo añado debajo
};

MODELO.SIN_CATEGORIA = new MODELO.Categoria(0, "Sin Clasificar");
